package com.yangjiayu.service.impl;

import cn.hutool.json.JSONNull;
import cn.hutool.json.JSONUtil;
import com.yangjiayu.bean.ChatEntity;
import com.yangjiayu.bean.ChatResponseEntity;
import com.yangjiayu.bean.SearchResult;
import com.yangjiayu.enums.SSEMsgType;
import com.yangjiayu.service.ChatService;
import com.yangjiayu.service.SearXngService;
import com.yangjiayu.utils.SSEServer;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
import org.springframework.ai.chat.memory.ChatMemory;
import org.springframework.ai.chat.model.ChatResponse;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.document.Document;
import org.springframework.ai.tool.ToolCallbackProvider;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Flux;

import java.util.List;
import java.util.stream.Collectors;

/**
 * @Classname ChatServiceImpl
 * @Description TODO
 * @Date 2025/8/12 20:19
 * @Created by YangJiaYu
 */
@Service
@Slf4j
public class ChatServiceImpl implements ChatService {

    private ChatClient chatClient;

    private ChatMemory chatMemory;

    @Resource
    private SearXngService searXngService;

    private String systemPrompt = """
    你是一个非常聪明的人工智能助手，可以帮我解决很多问题，我为你取一个名字：'YangJiaYu'
""";

    /*
    提示词的三大类型
    1.System
    2.user
    3.assistant
     */

    // 构造器注入，自动配置方式（推荐）
    public ChatServiceImpl(ChatClient.Builder chatClientBuilder, ToolCallbackProvider tools,ChatMemory chatMemory) {

        // 先 new 一个简单实现，让项目先跑起来
        // ChatMemory chatMemory = new InMemoryChatMemory();

        this.chatClient = chatClientBuilder
            .defaultToolCallbacks(tools)
            .defaultAdvisors(MessageChatMemoryAdvisor.builder(chatMemory).build())
//            .defaultSystem(systemPrompt)
        .build()
        ;
    }

    @Override
    public String chatTest(String prompt) {
        return chatClient.prompt(prompt).call().content();

    }

    @Override
    public Flux<ChatResponse> streamResponse(String prompt) {
        return chatClient.prompt(prompt).stream().chatResponse();
    }

    @Override
    public Flux<String> streamStr(String prompt) {
        return chatClient.prompt(prompt).stream().content();
    }

    @Override
    public void doChat(ChatEntity chatEntity) {
        String userId = chatEntity.getCurrentUserName();
        String prompt = chatEntity.getMessage();
        String botMsgId = chatEntity.getBotMsgId();

        Flux<String> stringFlux = chatClient.prompt(prompt).stream().content();

        List<String> list = stringFlux.toStream().map(chatResponse -> {
            String content = chatResponse.toString();
            SSEServer.sendMsg(userId, content, SSEMsgType.ADD);
            log.info("content:{}", content);
            return content;
        }).collect(Collectors.toList());

        String fullContent = list.stream().collect(Collectors.joining());
        // 可以保存到数据库

        ChatResponseEntity chatResponseEntity = new  ChatResponseEntity(fullContent,botMsgId);

        SSEServer.sendMsg(userId, JSONUtil.toJsonStr(chatResponseEntity), SSEMsgType.FINISH);


    }

    // Dify 智能体引擎构建平台
    private static final String RAG_PROMPT = """
        基于上下文的知识库内容回答问题：
        【上下文】
        {context}
        
        【问题】
        {question}
        
        【输出】
        如果没有查到，请回复：不知道
        如果查到，请回复具体的内容。不相关的近似内容不必提到。
        """;


    @Override
    public void doChatRagSearch(ChatEntity chatEntity, List<Document> ragContext) {
        String userId = chatEntity.getCurrentUserName();
        String question = chatEntity.getMessage();
        String botMsgId = chatEntity.getBotMsgId();

        // 构建提示词
        String context = null;
        if(ragContext!=null && ragContext.size() > 0){
            context = ragContext.stream().map(Document::getText).collect(Collectors.joining("\n"));
        }
        // 组装提示词
        Prompt prompt = new Prompt(RAG_PROMPT
            .replace("{context}",context)
            .replace("{question}",question)
        );

        System.out.println(prompt.toString());


        Flux<String> stringFlux = chatClient.prompt(prompt).stream().content();

        List<String> list = stringFlux.toStream().map(chatResponse -> {
            String content = chatResponse.toString();
            SSEServer.sendMsg(userId, content, SSEMsgType.ADD);
            log.info("content:{}", content);
            return content;
        }).collect(Collectors.toList());

        String fullContent = list.stream().collect(Collectors.joining());
        // 可以保存到数据库

        ChatResponseEntity chatResponseEntity = new  ChatResponseEntity(fullContent,botMsgId);

        SSEServer.sendMsg(userId, JSONUtil.toJsonStr(chatResponseEntity), SSEMsgType.FINISH);

    }

    private static final String SEARXNG_PROMPT = """
        你是一个互联网搜索大师，请基于以下互联网返回的结果作为上下文，根据你的理解结合用户的提问综合后，生成并且输出专业的回答：
        【上下文】
        {context}
        
        【问题】
        {question}
        
        【输出】
        如果没有查到，请回复：不知道
        如果查到，请回复具体的内容。
        """;

    @Override
    public void doInternetSearch(ChatEntity chatEntity) {

        String userId = chatEntity.getCurrentUserName();
        String question = chatEntity.getMessage();
        String botMsgId = chatEntity.getBotMsgId();

        List<SearchResult>searchResults = searXngService.search(question);

        String finalPrompt = buildSearXNGPrompt(question, searchResults);

        // 组装提示词
        Prompt prompt = new Prompt(finalPrompt);

        System.out.println(prompt.toString());


        Flux<String> stringFlux = chatClient.prompt(prompt).stream().content();

        List<String> list = stringFlux.toStream().map(chatResponse -> {
            String content = chatResponse.toString();
            SSEServer.sendMsg(userId, content, SSEMsgType.ADD);
            log.info("content:{}", content);
            return content;
        }).collect(Collectors.toList());

        String fullContent = list.stream().collect(Collectors.joining());
        // 可以保存到数据库

        ChatResponseEntity chatResponseEntity = new  ChatResponseEntity(fullContent,botMsgId);

        SSEServer.sendMsg(userId, JSONUtil.toJsonStr(chatResponseEntity), SSEMsgType.FINISH);

    }

    private static String buildSearXNGPrompt(String question,List<SearchResult> searchResults) {

        StringBuilder context = new StringBuilder();

        searchResults.forEach(searchResult -> {
            context.append(String.format("<context>\n[来源] %s \n [摘要] %s \n </context>\n",
                searchResult.getUrl(),
                searchResult.getContent()));

        });

        return SEARXNG_PROMPT
            .replace("{context}",context.toString())
            .replace("{question}",question);
    }
}
